package com.danco.training.zaneuskaya.controller;

import java.io.IOException;
import java.util.Date;
import java.util.List;






import com.danco.training.zaneuskaya.api.BookController;
import com.danco.training.zaneuskaya.api.OrderController;
import com.danco.training.zaneuskaya.communication.MessageAnalyzer;
import com.danco.training.zaneuskaya.dependency.DependencyConfiguration;
import com.danco.training.zaneuskaya.domain.Book;
import com.danco.training.zaneuskaya.domain.Order;
import com.danco.training.zaneuskaya.view.IOUtil;

public class OrderControllerImpl implements OrderController {

	private static final String UPDATE_ENTITY = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;updateEntity";
	private static final String READ_ENTITY_LIST_FROM_FILE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;readEntityList";
	private static final String SAVE_ENTITY_LIST_TO_FILE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;saveEntityListToFile";
	private static final String CREATE_ORDER_COPY = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;createOrderCopy";
	private static final String EXECUTE_ORDER_BY_ID = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;executeOrderById";
	private static final String REMOVE_BOOK_FROM_ORDER = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;removeBookFromOrder";
	private static final String REMOVE_ENTITY_BY_ID = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;removeEntityById";
	private static final String GET_BY_ID = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getById";
	private static final String ADD_BOOK_TO_ORDER = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;addBookToOrder";
	private static final String GET_BY_BOOK_ID = "com.danco.training.zaneuskaya.service.impl.BookServiceImpl;getById";
	private static final String ADD_ENTITY = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;addEntity";
	private static final String GET_EXECUTED_ORDERS_SORTED_BY_PRICE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getExecutedOrdersSortedByPrice";
	private static final String GET_EXECUTED_ORDERS_SORTED_BY_ORDER_DATE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getExecutedOrdersSortedByOrderDate";
	private static final String GET_NOT_EXECUTED_ORDERS = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getNotExecutedOrders";
	private static final String GET_EXECUTED_ORDERS = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getExecutedOrders";
	private static final String GET_ORDERS_SORTED_BY_ORDER_DATE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getOrdersSortedByOrderDate";
	private static final String GET_LIST = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getList";

	private static final String READ_ORDER_LIST_FROM_FILE_MESSAGE = "Enter directory and file name to read order list ";
	private static final String SAVED_BY_DEFAULT_IN = "Saved by default in ";
	private static final String FILE_TO_SAVE_ORDER_LIST = "d:\\file1.csv";
	private static final String SAVE_ORDER_LIST_TO_FILE_MESSAGE = "Enter directory and file name for saving";
	private static final String COPY_ORDER_MESSAGE = "Enter order Id to copy";
	private static final String EXECUTE_ORDER_MESSAGE = "Enter order id to execute";

	private static final String ENTER_BOOK_ID_TO_DELETE = "Enter book id to delete";
	private static final String DELETE_BOOK_FROM_ORDER_MESSAGE = "Enter order id to delete book from order";
	private static final String ADD_BOOK_TO_ORDER_MESSAGE = "Enter order id to add book";
	private static final String DELETE_ORDER_MESSAGE = "Enter order Id";
	private static final String CHANGE_ORDER_STATE_TRUE = "y";
	private static final String CHANGE_ORDER_STATE = "Change order state : y/n";
	private static final String UPDATE_ORDER_MESSAGE = "Enter order Id for modifying";
	private static final String ORDER_NOT_EXISTED_MESSAGE = "Order not existed";
	private static final String PRINT_ORDER_INFO_MESSAGE = "Enter order Id:";
	private static final String ENTER_BOOK_ID_TO_ADD_IN_ORDER = "Enter book Id to add:";
	private static final String CREATE_ORDER_MESSAGE = "Order creation";
	private static final String PRINT_EXECUTED_ORDER_LIST_SORTED_BY_PRICE = "Executed Orders in OrderStorage sorted by price ";
	private static final String PRINT_EXECUTED_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE = "Executed Orders in OrderStorage sorted by execution date ";
	private static final String ENTER_DATE_TO_FOR_ORDER_SORTING = "Enter date day to";
	private static final String ENTER_DATE_FROM_FOR_ORDER_SORTING = "Enter date from ";
	private static final String PRINT_NOT_EXECUTED_ORDERS_MESSAGE = "Not Executed Orders in OrderStorage ";
	private static final String PRINT_EXECUTED_ORDERS_MESSAGE = "Executed Orders in OrderStorage ";
	private static final String PRINT_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE = "Orders in OrderStorage sorted by execution date";
	private static final String PRINT_ORDER_LIST_MESSAGE = "Orders in OrderStorage";

	private BookController bookController = (BookController) DependencyConfiguration
			.getInstanceByClassName(BookController.class);

	@SuppressWarnings("unchecked")
	public void printOrderList() {
		IOUtil.write(PRINT_ORDER_LIST_MESSAGE);
		List<Order> orders;
		try {

			orders = (List<Order>) MessageAnalyzer
					.executeMethod(GET_LIST, null);
			for (Order order : orders) {
				IOUtil.write(orderInfo(order.getId()));
			}
		} catch (IOException e) {
			IOUtil.write(e.getMessage() + "Wrong Input");
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void printOrderListSortedByOrderDate() {
		IOUtil.write(PRINT_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE);

		List<Order> sortedOrders = null;
		try {

			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(
					GET_ORDERS_SORTED_BY_ORDER_DATE, new Object[] {});
			for (Order order : sortedOrders) {
				IOUtil.write(orderInfo(order.getId()));
			}

		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void printOrderListSortedByPrice() {
		List<Order> sortedOrders = null;
		try {

			sortedOrders = (List<Order>) MessageAnalyzer
					.executeMethod(
							"com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getOrdersSortedByTotalPrice",
							new Object[] {});
			for (Order order : sortedOrders) {
				IOUtil.write(orderInfo(order.getId()));
			}

		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
	}

	public void printExecutedOrders() {
		IOUtil.write(PRINT_EXECUTED_ORDERS_MESSAGE);

		List<Order> sortedOrders = null;
		try {

			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(
					GET_EXECUTED_ORDERS, new Object[] {});
			for (Order order : sortedOrders) {
				IOUtil.write(orderInfo(order.getId()));
			}

		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void printNotExecutedOrders() {
		IOUtil.write(PRINT_NOT_EXECUTED_ORDERS_MESSAGE);

		List<Order> sortedOrders = null;
		try {

			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(
					GET_NOT_EXECUTED_ORDERS, new Object[] {});
			for (Order order : sortedOrders) {
				IOUtil.write(orderInfo(order.getId()));
			}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void printExecutedOrderListSortedByOrderDate() {
		IOUtil.write(ENTER_DATE_FROM_FOR_ORDER_SORTING);
		try {
			Date d1 = IOUtil.readDate();
			IOUtil.write(ENTER_DATE_TO_FOR_ORDER_SORTING);

			Date d2 = IOUtil.readDate();
			IOUtil.write(PRINT_EXECUTED_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE);

			List<Order> sortedOrders = null;

			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(
					GET_EXECUTED_ORDERS_SORTED_BY_ORDER_DATE, new Object[] {
							d1, d2 });
			for (Order order : sortedOrders) {
				IOUtil.write(orderInfo(order.getId()));
			}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void printExecutedOrderListSortedByPrice() {
		IOUtil.write(ENTER_DATE_FROM_FOR_ORDER_SORTING);

		Date d1 = IOUtil.readDate();
		IOUtil.write(ENTER_DATE_TO_FOR_ORDER_SORTING);

		Date d2 = IOUtil.readDate();
		IOUtil.write(PRINT_EXECUTED_ORDER_LIST_SORTED_BY_PRICE);

		List<Order> sortedOrders = null;
		try {

			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(
					GET_EXECUTED_ORDERS_SORTED_BY_PRICE,
					new Object[] { d1, d2 });
			for (Order order : sortedOrders) {
				IOUtil.write(orderInfo(order.getId()));
			}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void createOrder() {
		IOUtil.write(CREATE_ORDER_MESSAGE);

		try {

			Order order = new Order();
			MessageAnalyzer.executeMethod(ADD_ENTITY, new Object[] { order });
			IOUtil.write(ENTER_BOOK_ID_TO_ADD_IN_ORDER);
			bookController.printBookList();
			int bookId = IOUtil.readInt();
			Book book = (Book) MessageAnalyzer.executeMethod(GET_BY_BOOK_ID,
					new Object[] { bookId });
			MessageAnalyzer.executeMethod(ADD_BOOK_TO_ORDER, new Object[] {
					order, book });
			IOUtil.write(orderInfo(order.getId()));
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {

			IOUtil.write(e.getMessage());
		}

	}

	public void printOrderInfo() {
		IOUtil.write(PRINT_ORDER_INFO_MESSAGE);
		int id = IOUtil.readInt();
		Order order = null;

		try {
			order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
					new Object[] { id });

			while (order == null) {
				IOUtil.write(ORDER_NOT_EXISTED_MESSAGE);
				IOUtil.write(PRINT_ORDER_INFO_MESSAGE);
				id = IOUtil.readInt();
			}
			IOUtil.write(orderInfo(order.getId()));
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		}
	}

	public String orderInfo(Integer id) {
		StringBuffer str = new StringBuffer(id + "  ");
		Order order = null;
		try {
			order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
					new Object[] { id });

			str.append(" Books:");
			for (Book book : order.getBooks()) {
				str.append(book.getId());
				str.append(" ");

			}
			str.append(" Executed: ");
			str.append(order.isExecuted() + "  ");
			str.append(order.getTotalPrice());

		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		return str.toString();
	}

	public void updateOrder() {

		Order order = null;

		while (order == null) {

			IOUtil.write(UPDATE_ORDER_MESSAGE);
			int id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
						new Object[] { id });
				IOUtil.write(CHANGE_ORDER_STATE);
				if (!IOUtil.read().equals(CHANGE_ORDER_STATE_TRUE)) {
					order.setExecuted(!order.isExecuted());
				}
				MessageAnalyzer.executeMethod(UPDATE_ENTITY,
						new Object[] { order });
				IOUtil.write(orderInfo(order.getId()));

			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

	}

	public void deleteOrder() {
		Order order = null;
		int id = 0;
		while (order == null) {
			IOUtil.write(DELETE_ORDER_MESSAGE);
			id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
						new Object[] { id });
				MessageAnalyzer.executeMethod(REMOVE_ENTITY_BY_ID,
						new Object[] { id });
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

	}

	public void addBookToOrder() {
		Order order = null;
		Book book = null;
		int id = 0;
		while (order == null) {

			IOUtil.write(ADD_BOOK_TO_ORDER_MESSAGE);
			id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
						new Object[] { id });
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

		bookController.printBookList();

		while (book == null) {

			IOUtil.write(ENTER_BOOK_ID_TO_ADD_IN_ORDER);

			int bookId = IOUtil.readInt();
			try {
				book = (Book) MessageAnalyzer.executeMethod(GET_BY_BOOK_ID,
						new Object[] { bookId });

				MessageAnalyzer.executeMethod(ADD_BOOK_TO_ORDER, new Object[] {
						order, book });
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

	}

	public void deleteBookFromOrder() {
		Order order = null;
		while (order == null) {
			IOUtil.write(DELETE_BOOK_FROM_ORDER_MESSAGE);
			int id = IOUtil.readInt();
			Book book = null;
			try {

				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
						new Object[] { id });
				while (book == null) {

					IOUtil.write(ENTER_BOOK_ID_TO_DELETE);
					int bookId = IOUtil.readInt();

					book = (Book) MessageAnalyzer.executeMethod(GET_BY_BOOK_ID,
							new Object[] { bookId });
				}
				MessageAnalyzer.executeMethod(REMOVE_BOOK_FROM_ORDER,
						new Object[] { order, book });
				IOUtil.write(orderInfo(order.getId()));
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

	}

	public void executeOrder() {
		Order order = null;
		int id = 0;
		while (order == null) {

			IOUtil.write(EXECUTE_ORDER_MESSAGE);
			id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
						new Object[] { id });

				MessageAnalyzer.executeMethod(EXECUTE_ORDER_BY_ID,
						new Object[] { id });
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

	}

	public void copyOrder() {
		Order order = null;
		Order copy = null;
		while (order == null) {

			IOUtil.write(COPY_ORDER_MESSAGE);
			int id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,
						new Object[] { id });
				copy = (Order) MessageAnalyzer.executeMethod(CREATE_ORDER_COPY,
						new Object[] { order });
				IOUtil.write(orderInfo(copy.getId()));
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}

	}

	public void saveOrderListToFile() {
		IOUtil.write(SAVE_ORDER_LIST_TO_FILE_MESSAGE);
		String file = IOUtil.read();
		if (file.isEmpty()) {
			file = FILE_TO_SAVE_ORDER_LIST;
			IOUtil.write(SAVED_BY_DEFAULT_IN + FILE_TO_SAVE_ORDER_LIST);

		}
		try {
			MessageAnalyzer.executeMethod(SAVE_ENTITY_LIST_TO_FILE,
					new Object[] { file });
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

	public void readOrderListFromFile() {
		IOUtil.write(READ_ORDER_LIST_FROM_FILE_MESSAGE);
		String file = IOUtil.read();
		if (file.isEmpty()) {
			file = FILE_TO_SAVE_ORDER_LIST;

		}
		List<Order> orders = null;
		try {
			orders = (List<Order>) MessageAnalyzer.executeMethod(
					READ_ENTITY_LIST_FROM_FILE, new Object[] { file });

			for (Order or : orders) {

				MessageAnalyzer.executeMethod(ADD_ENTITY, new Object[] { or });
			}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}

	}

}
